package org.dev.vlp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dev.vlp.constants.Common;
import org.dev.vlp.constants.LanguageEnum;
import org.dev.vlp.constants.SearchType;
import org.dev.vlp.entity.Book;
import org.dev.vlp.entity.Statistics;
import org.dev.vlp.entity.Word;
import org.dev.vlp.exception.ApiException;
import org.dev.vlp.mapper.BookMapper;
import org.dev.vlp.mapper.StatisticsMapper;
import org.dev.vlp.service.BookService;
import org.dev.vlp.service.StatisticsService;
import org.dev.vlp.service.WordService;
import org.dev.vlp.mapper.WordMapper;
import org.dev.vlp.utils.PageResult;
import org.dev.vlp.utils.RandomUtils;
import org.dev.vlp.vo.EstimationWordVo;
import org.dev.vlp.vo.VocabularyEstimationVo;
import org.dev.vlp.vo.VocabularyVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
* @author 86184
* @description 针对表【vlp_vi_word】的数据库操作Service实现
* @createDate 2023-01-15 21:33:27
*/
@Service
public class WordServiceImpl extends ServiceImpl<WordMapper, Word>
    implements WordService {

    @Autowired
    private WordMapper wordMapper;

    @Autowired
    private StatisticsService statisticsService;

    @Autowired
    private StatisticsMapper statisticsMapper;

    @Autowired
    private BookMapper bookMapper;

    @Override
    public Word getWordDetail(long id, Long userId) {

        int lan = statisticsService.getLan(userId.intValue());
        LanguageEnum languageEnum = LanguageEnum.get(lan);
        String tableName = languageEnum.getWordTableEnum().getTableName();

        Word word = wordMapper.getWord((int) id, tableName);
        if (word == null) {
            throw new ApiException("单词不存在");
        }
        return word;
    }

    @Override
    public VocabularyEstimationVo listEstimationWords(int userId) {
        int lan = statisticsService.getLan(userId);
        LanguageEnum languageEnum = LanguageEnum.get(lan);
        String word = languageEnum.getWordTableEnum().getTableName();
        int bookId=languageEnum.getBookIdEnum().getBookId();
        QueryWrapper<Book> bookQueryWrapper = new QueryWrapper<>();
        bookQueryWrapper.eq("lan",lan);
        int count = Common.vocabNum[lan-1];
//

        // 无需考虑容量问题
        List<EstimationWordVo> estimationWordList = new LinkedList<>();
        Integer[] estimateWordNums = null;
        if(count==5){
            estimateWordNums=Common.ESTIMATE_WORD_NUMS;
        }
        if(count==4){
            estimateWordNums=Common.ESTIMATE_WORD_NUMS4;
        }
        if(count==2){
            estimateWordNums=Common.ESTIMATE_WORD_NUMS2;
        }

        // TODO: 数据库单词的level和难度是负相关的（5最简单），后面改一下
        for (int i = 1; i <= count; i++) {
            List<EstimationWordVo> levelWordList = wordMapper.getRandomEstimationWords(bookId+i-1, estimateWordNums[i-1],word);
            estimationWordList.addAll(levelWordList);
        }
        VocabularyEstimationVo vocabularyEstimationVO = new VocabularyEstimationVo();
        vocabularyEstimationVO.setEstimationWordList(estimationWordList);
        this.genAndSetOptions(vocabularyEstimationVO);
        return vocabularyEstimationVO;
    }

    @Override
    public List<EstimationWordVo> getGameWords(int lan) {
        LanguageEnum languageEnum = LanguageEnum.get(lan);
        String word = languageEnum.getWordTableEnum().getTableName();
        List<EstimationWordVo> gameWords = wordMapper.getGameWords(15, word);
        VocabularyEstimationVo vocabularyEstimationVO = new VocabularyEstimationVo();
        vocabularyEstimationVO.setEstimationWordList(gameWords);
        this.genAndSetOptions(vocabularyEstimationVO);
        return vocabularyEstimationVO.getEstimationWordList();
    }

    /**
     * 计算词汇量
     *
     * @param levelRightCounts 每个等级答对的题目数量
     * @return
     */
    @Override
    public VocabularyVo calculate(Long user,List<Integer> levelRightCounts) {
        int result = 0;
        double rightRate = 0;
        int lan = statisticsService.getLan(user.intValue());
        LanguageEnum languageEnum = LanguageEnum.get(lan);
        int beginId = languageEnum.getBookIdEnum().getBookId();
        QueryWrapper<Book> bookQueryWrapper = new QueryWrapper<>();
        bookQueryWrapper.eq("lan",lan);
        int count = levelRightCounts.size();
        Integer[] wordNum=null;
        if(count==5){
            wordNum=Common.ESTIMATE_WORD_NUMS;
        }
        if(count==4){
            wordNum=Common.ESTIMATE_WORD_NUMS4;
        }
        if(count==2){
            wordNum=Common.ESTIMATE_WORD_NUMS2;
        }
        for (int i = 0; i < count; i++) {
            rightRate = levelRightCounts.get(i) / (double)wordNum [i];

            if (i > 0) {
                /*
                    如果题目不属于第一级，则将上一级答对的比率和本级相乘
                    然后用这个比率乘以固定的预估值作为该级别的预估次数
                */
                double lastRightRate = levelRightCounts.get(i - 1) / (double) wordNum[i - 1];
                if (lastRightRate == 0) {
                    lastRightRate = 0.1;
                }
                rightRate *= lastRightRate;
            }
            result += Common.SCALE * rightRate;
        }

        // TODO: 2023/3/8 根据词汇量确定用户要背的词书book
        // 如果用户已经有词书，则做完测试不必向数据库加入词书，否则加上词书
        // TODO  2023.10.31 如何根据每本词书的词量确定词汇量
        int book = result / 1000;

//        QueryWrapper<Statistics> statisticsQueryWrapper = new QueryWrapper<>();
//        statisticsQueryWrapper.eq("user_id",user).eq("lan_id",lan);
//        List<Statistics> statistics1 = statisticsMapper.selectList(statisticsQueryWrapper);
//        if(statistics1.size()==0){
//            statisticsMapper.insert(new Statistics(user.intValue(), lan, book+beginId-1));
//        }

        VocabularyVo vocabularyVo = new VocabularyVo();
        Book book1 = bookMapper.selectById(book + beginId - 1);
        vocabularyVo.setBook(book1);
        vocabularyVo.setResult(result);

        return vocabularyVo;
    }

    /**
     * 生成随机的4个选项
     *
     * @param vocabularyEstimationVO
     */
    private void genAndSetOptions(VocabularyEstimationVo vocabularyEstimationVO) {
        List<EstimationWordVo> estimationWordList = vocabularyEstimationVO.getEstimationWordList();
        for (int i = 0; i < estimationWordList.size(); i++) {
            int[] optionIndexs = RandomUtils.get3OptionIndexs(i, estimationWordList.size(), estimationWordList);
            List<String> options = new LinkedList<>();
            for (int optionIndex : optionIndexs) {
                options.add(estimationWordList.get(optionIndex).getTranslationCh());
            }
            options.add(estimationWordList.get(i).getTranslationCh());
            // 选项打乱
            Collections.shuffle(options);
            estimationWordList.get(i).setOptions(options);
        }
    }



    @Override
    public PageResult search(int currentPage, int pageSize, int type, Long uid, String keyWord, Long bookId) {
        int lan = statisticsService.getLan(uid.intValue());
        LanguageEnum languageEnum = LanguageEnum.get(lan);
//        String wordBookTable = languageEnum.getWordBookTableEnum().getTableName();
        String wordTable = languageEnum.getWordTableEnum().getTableName();
        // 全文检索
        if (type == SearchType.ALL) {
            List<Word> words = wordMapper.searchWord(null, (currentPage - 1) * pageSize, pageSize, keyWord,wordTable);
            Long total = wordMapper.searchWordCount(null, keyWord,wordTable);
            return new PageResult(words, total, pageSize);
        } else if (type == SearchType.IN_BOOK) {
            List<Word> words = wordMapper.searchWord(bookId, (currentPage - 1) * pageSize, pageSize, keyWord,wordTable);
            Long total = wordMapper.searchWordCount(bookId, keyWord,wordTable);
            return new PageResult(words, total, pageSize);
        } else {
            throw new ApiException("检索类型错误");
        }
    }

    @Override
    public PageResult getBookWordPage(Long bookId, int currentPage, int pageSize,Long uid) {
        int lan = statisticsService.getLan(uid.intValue());
        LanguageEnum languageEnum = LanguageEnum.get(lan);
//        String wordBookTable = languageEnum.getWordBookTableEnum().getTableName();
        String wordTable = languageEnum.getWordTableEnum().getTableName();
        List<Word> bookWordByPage = wordMapper.getBookWordByPage(
                bookId, (currentPage - 1) * pageSize, pageSize,wordTable);
        Long total = wordMapper.getBookWordByPageCount(bookId,wordTable);
        return new PageResult(bookWordByPage, total, pageSize);
    }



}




